import pygame
import random
import sys
from config import Config
import math

pygame.init()
config = Config()

# 设置网格大小和智能体数量
GRID_SIZE = config.GRID_SIZE
AGENT_COUNT = config.AGENT_COUNT
CELL_SIZE = config.CELL_SIZE  # 根据屏幕大小调整单元格大小

# 创建屏幕
screen = pygame.display.set_mode(config.SCREEN)
pygame.display.set_caption('智能体游戏')

# 设置字体
font = pygame.font.Font(None, config.FONT_SIZE)


# 生成随机颜色
def random_color():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))


def judge_move_direction(x1, y1, x2, y2, judge):
    def _judge(delta_x, delta_y):
        # 靠近
        if delta_x == 0:  # 如果水平距离为0，垂直方向上移动
            if delta_y > 0:  # 向上移动
                direction = 'down'
            else:  # 向下移动
                direction = 'up'
        elif delta_x > 0:  # 如果水平距离为正，向右移动
            direction = 'right'
        else:  # 如果水平距离为负，向左移动
            direction = 'left'

        # 根据delta_y的值确定是上还是下
        if delta_y > 0:
            direction += '-down'
        else:
            direction += '-up'
        return direction

    # 计算两个智能体之间的水平距离和垂直距离
    delta_x = x2 - x1
    delta_y = y2 - y1
    if judge == 'near':
        direction = _judge(delta_x, delta_y)
    else:
        direction = _judge(-1 * delta_x, -1 * delta_y)

    return direction


class Agent:
    def __init__(self, x, y, health, level=1):
        self.x = x
        self.y = y
        self.health = health  # 当前状态血量
        self.max_health = health  # 最大血量
        self.level = level  # 当前等级
        self.speed = math.log2(level + 1)
        self.level_up_kill_number = 0  # 升级所需要吃掉其他智能体的个数，默认为当前等级的2倍
        self.attack = level  # 攻击力，设置为当前等级
        self.color = random_color()  # 为每个智能体设置随机颜色
        self.last_direction = None
        self.size = int((self.health / 10) * CELL_SIZE)
        self.detect_range = self.level + 2  # 智能体探测范围

    def step(self):
        # 检测恢复血量
        if self.health < self.max_health:
            self.health += 0.02 * self.level

        if self.health > self.max_health:
            self.health = self.max_health

        # 检测升级
        if self.level_up_kill_number > self.level:  # 如果满足升级条件
            self.level += 1
            self.attack = self.level
            self.level_up_kill_number = 0
            self.max_health += 10
            self.health = self.max_health
            self.detect_range = self.level + 2
            self.speed = math.log2(self.level + 1)  # 速度与等级线性相关

        # 确保智能体大小不会小于一个最小值
        self.size = max(int((self.health / 10) * CELL_SIZE), 20)

    def get_agent_score(self):
        return self.level * 10 + self.level_up_kill_number

    def move(self, neighbors):
        if len(neighbors) != 0 and random.random() < 0.8:
            low_than_me = None
            high_than_me = None
            for agent in neighbors:
                # 判断智能体i是否可以击杀j
                agent_i_attack_num = agent.health / self.attack  # 智能体i的攻击次数
                agent_j_attack_num = self.health / agent.attack  # 智能体j的攻击次数
                if agent_i_attack_num < agent_j_attack_num:  # 当前自身智能体可以击杀范围内智能体
                    low_than_me = agent
                else:
                    high_than_me = agent

            if low_than_me:
                direction = judge_move_direction(self.x, self.y, low_than_me.x, low_than_me.y, judge='near')
            if high_than_me:
                # 优先躲避,如果有危险，则覆盖上一决策
                direction = judge_move_direction(self.x, self.y, high_than_me.x, high_than_me.y, judge='far')

        else:
            # 确定可用的移动方向
            available_directions = ['up', 'down', 'left', 'right']
            if self.x > 0:
                available_directions.append('left')
                available_directions.append('up-left')
                available_directions.append('down-left')
            if self.x < GRID_SIZE - 1:
                available_directions.append('right')
                available_directions.append('up-right')
                available_directions.append('down-right')
            if self.y > 0:
                available_directions.append('up')
                available_directions.append('up-left')
                available_directions.append('up-right')
            if self.y < GRID_SIZE - 1:
                available_directions.append('down')
                available_directions.append('down-left')
                available_directions.append('down-right')
            if random.random() < 0.7 and self.last_direction in available_directions:
                direction = self.last_direction
            else:
                # 从可用的移动方向中随机选择一个
                direction = random.choice(available_directions)
            self.last_direction = direction

        # 根据选择的移动方向更新位置
        if direction == 'up':
            self.y -= self.speed
        elif direction == 'down':
            self.y += self.speed
        elif direction == 'left':
            self.x -= self.speed
        elif direction == 'right':
            self.x += self.speed
        elif direction == 'up-left' or direction == 'left-up':
            self.y -= self.speed
            self.x -= self.speed
        elif direction == 'up-right' or direction == 'right-up':
            self.y -= self.speed
            self.x += self.speed
        elif direction == 'down-left' or direction == 'left-down':
            self.y += self.speed
            self.x -= self.speed
        elif direction == 'down-right' or direction == 'right-down':
            self.y += self.speed
            self.x += self.speed

    def draw(self):
        size = self.size
        # 计算绘制的位置，确保智能体在网格中心
        draw_x = self.x * CELL_SIZE + (CELL_SIZE - size) // 2
        draw_y = self.y * CELL_SIZE + (CELL_SIZE - size) // 2
        # 绘制圆形智能体
        pygame.draw.circle(screen, self.color, (draw_x + size // 2, draw_y + size // 2), size // 2)

        pygame.draw.circle(screen, config.BLACK, (draw_x + size // 2, draw_y + size // 2), size // 2, width=1)

        pygame.draw.circle(screen, config.BLACK, (draw_x + size // 2, draw_y + size // 2),
                           self.detect_range * CELL_SIZE, width=1)

        # 在智能体上显示健康值
        health_surface = font.render(str(self.level), True, config.BLACK)
        health_rect = health_surface.get_rect(center=(draw_x + size // 2, draw_y + size // 2))
        screen.blit(health_surface, health_rect)


# 食物类
class Food:
    def __init__(self, x, y, satiety):
        self.x = x
        self.y = y
        self.satiety = satiety
        self.color = config.FOOD_COLOR  # 食物颜色
        self.size = config.FOOD_SIZE

    def draw(self):
        # 绘制食物
        FOOD_SIZE = self.size
        pygame.draw.rect(screen, self.color, (self.x * CELL_SIZE, self.y * CELL_SIZE, FOOD_SIZE, FOOD_SIZE))
